home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianLists.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
12KB
|
669 lines
/*ScianLists.c
Eric Pepke
March 28, 1990
Routines for lists of things
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianNames.h"
#include "ScianLists.h"
#include "ScianIDs.h"
#include "ScianGarbageMan.h"
#include "ScianWindows.h"
#include "ScianObjWindows.h"
#include "ScianDraw.h"
ObjPtr listClass = NULLOBJ;
ObjPtr CopyList(list)
ObjPtr list;
/*Returns a copy of list*/
{
ObjPtr retVal;
ThingListPtr runner;
if (!list || !IsList(list))
{
return NULLOBJ;
}
retVal = NewList();
runner = LISTOF(list);
while (runner)
{
PostfixList(retVal, runner -> thing);
runner = runner -> next;
}
return retVal;
}
static ObjPtr FindListObject(list, name)
ObjPtr list;
char *name;
/*Finds an object with name in list. Returns it or NULLOBJ*/
{
ObjPtr retVal;
ThingListPtr runner;
ObjPtr objName;
retVal = NULLOBJ;
/*First check to see if I am the object*/
objName = GetVar(list, NAME);
if (objName && IsString(objName) && ObjectNameMatches(name, GetString(objName)))
{
if (!retVal)
{
retVal = NewList();
}
PostfixList(retVal, list);
}
/*Now see if one of my contents is the object*/
runner = LISTOF(list);
while (runner)
{
ObjPtr foundObject;
foundObject = FindNamedObject(runner -> thing, name);
if (foundObject)
{
if (!retVal)
{
retVal = NewList();
}
AppendList(retVal, foundObject);
}
runner = runner -> next;
}
return retVal;
}
static ObjPtr ForAllListObjects(list, routine)
ObjPtr list;
FuncTyp routine;
/*Does routine on list*/
{
ThingListPtr runner;
(*routine)(list);
/*Now do on contents*/
runner = LISTOF(list);
while (runner)
{
ForAllObjects(runner -> thing, routine);
runner = runner -> next;
}
return ObjTrue;
}
ObjPtr NewList()
/*Returns a new, empty list*/
{
LPtr retVal;
retVal = (LPtr) NewObject(listClass, sizeof(List) - sizeof(Thing));
if (!retVal)
{
return 0;
}
SETOBJTYPE(retVal -> thing . flags, LIST);
retVal -> list = 0;
retVal -> lastNode = 0;
return (ObjPtr) retVal;
}
Bool PrefixList(list, thing)
ObjPtr list;
ObjPtr thing;
/*Prefixes thing on to the beginning of list*/
{
ThingListPtr newNode;
newNode = newp(ThingListElement);
if (!newNode)
{
OMErr();
return false;
}
newNode -> thing = thing;
newNode -> next = LISTOF(list);
if (!LISTOF(list))
{
((LPtr) list) -> lastNode = newNode;
}
LISTOF(list) = newNode;
return true;
}
Bool AppendList(list, appList)
ObjPtr list;
ObjPtr appList;
/*Postfixes appList on to the end of list*/
{
ThingListPtr runner;
runner = LISTOF(appList);
while (runner)
{
PostfixList(list, runner -> thing);
runner = runner -> next;
}
return true;
}
Bool PostfixList(list, thing)
ObjPtr list;
ObjPtr thing;
/*Postfixes thing on to the end of list*/
{
ThingListPtr newNode;
newNode = newp(ThingListElement);
if (!newNode)
{
OMErr();
return false;
}
newNode -> thing = thing;
newNode -> next = 0;
if (((LPtr) list) -> lastNode)
{
((LPtr) list) -> lastNode -> next = newNode;
((LPtr) list) -> lastNode = newNode;
}
else
{
((LPtr) list) -> list = newNode;
((LPtr) list) -> lastNode = newNode;
}
return true;
}
int ListCount(theList) /* return number of elements in a list */
ObjPtr theList;
{
int n=1;
ThingListPtr p;
if (!IsList(theList) || !(p = LISTOF(theList))) return 0;
while (p = p -> next) ++n;
return n;
}
ObjPtr GetListElem(theList, index) /* return element of a list (0=first) */
ObjPtr theList;
int index;
{
ThingListPtr p;
if (index < 0 || !IsList(theList)
|| !(p = LISTOF(theList))) return NIL;
do { if (--index < 0) return p -> thing; } while (p = p -> next);
return NIL; /* no more elements */
}
int WhichListIndex(list, object)
ObjPtr list, object;
/*Returns index of object in list, or -1*/
{
int k;
ThingListPtr runner;
k = 0;
runner = LISTOF(list);
while (runner)
{
if (runner -> thing == object) return k;
++k;
runner = runner -> next;
}
return -1;
}
int DeleteFromList(list, thing)
ObjPtr list;
ObjPtr thing;
/*Deletes all occurences of thing from list. Returns the number of things
it had to delete.*/
{
ThingListPtr *runner;
ThingListPtr lastNotDeleted;
int retVal;
retVal = 0;
lastNotDeleted = NULL;
runner = &(LISTOF(list));
while (*runner)
{
if ((*runner) -> thing == thing)
{
ThingListPtr next;
next = (*runner) -> next;
Free(*runner);
*runner = next;
++retVal;
}
else
{
lastNotDeleted = *runner;
runner = &(*runner) -> next;
}
}
((LPtr) list) -> lastNode = lastNotDeleted;
return retVal;
}
void EmptyList(list)
ObjPtr list;
/*Empties list, i.e. deletes all the elements*/
{
ThingListPtr *runner;
runner = &(LISTOF(list));
while (*runner)
{
ThingListPtr next;
next = (*runner) -> next;
Free(*runner);
*runner = next;
}
((LPtr) list) -> lastNode = NULL;
}
void DisposeList(list)
ObjPtr list;
/*Disposes of the contents of list*/
{
while (LISTOF(list))
{
ThingListPtr next;
next = LISTOF(list) -> next;
Free(LISTOF(list));
LISTOF(list) = next;
}
LISTOF(list) = 0;
Free(list);
}
#ifdef GRAPHICS
static void DrawRunner(runner)
ThingListPtr runner;
/*Draws a portion of a list starting at runner, back to front*/
{
if (runner)
{
ObjPtr oneObject;
DrawRunner(runner -> next);
oneObject = runner -> thing;
if (IsObject(oneObject))
{
DrawObject(oneObject);
}
else if (IsList(oneObject))
{
DrawList(oneObject);
}
}
}
#endif
void DrawList(list)
ObjPtr list;
/*Draws a list of objects list.*/
{
#ifdef GRAPHICS
ThingListPtr runner;
runner = LISTOF(list);
DrawRunner(runner);
#endif
}
ObjPtr PressList(list, x, y, flags)
ObjPtr list;
int x, y;
long flags;
/*Does a press in list starting at x, y.*/
{
#ifdef INTERACTIVE
ThingListPtr runner;
ObjPtr current;
current = GetVar((ObjPtr) selWinInfo, CURRENT);
if (current)
{
/*Give the current object first dibs*/
runner = LISTOF(list);
while (runner)
{
ObjPtr oneObject;
ObjPtr test; /*Test to see if press worked*/
oneObject = runner -> thing;
if (oneObject == current)
{
test = PressObject(oneObject, x, y, flags);
if (IsTrue(test))
{
return test;
}
}
runner = runner -> next;
}
}
runner = LISTOF(list);
while (runner)
{
ObjPtr oneObject;
ObjPtr test; /*Test to see if press worked*/
oneObject = runner -> thing;
if (oneObject != current)
{
test = PressObject(oneObject, x, y, flags);
if (IsTrue(test))
{
return test;
}
}
runner = runner -> next;
}
#endif
return ObjFalse;
}
ObjPtr TurnDialList(list, whichDial, delta, flags)
ObjPtr list;
int whichDial;
real delta;
long flags;
/*Does a dial turn in list with whichDial by delta amount*/
{
#ifdef INTERACTIVE
ThingListPtr runner;
ObjPtr current;
current = GetVar((ObjPtr) selWinInfo, CURRENT);
if (current)
{
/*Give the current object first dibs*/
runner = LISTOF(list);
while (runner)
{
ObjPtr oneObject;
ObjPtr test; /*Test to see if dial turn worked*/
oneObject = runner -> thing;
if (oneObject == current)
{
test = TurnDialObject(oneObject, whichDial, delta, flags);
if (IsTrue(test))
{
return test;
}
}
runner = runner -> next;
}
}
runner = LISTOF(list);
while (runner)
{
ObjPtr oneObject;
ObjPtr test; /*Test to see if dial turn worked*/
oneObject = runner -> thing;
if (oneObject != current)
{
test = TurnDialObject(oneObject, whichDial, delta, flags);
if (IsTrue(test))
{
return test;
}
}
runner = runner -> next;
}
#endif
return ObjFalse;
}
ObjPtr DropList(list, object, x, y)
ObjPtr list, object;
int x, y;
/*Drops object in list at x, y.*/
{
ThingListPtr runner;
runner = LISTOF(list);
while (runner)
{
ObjPtr oneObject;
ObjPtr test; /*Test to see if drop worked*/
oneObject = runner -> thing;
if (IsObject(oneObject))
{
test = DropObjects(oneObject, object, x, y);
if (IsTrue(test))
{
return test;
}
}
else if (IsList(oneObject))
{
test = DropList(oneObject, object, x, y);
if (IsTrue(test))
{
return test;
}
}
runner = runner -> next;
}
return ObjFalse;
}
#ifdef PROTO
ObjPtr KeyDownList(ObjPtr list, int key, long flags)
#else
ObjPtr KeyDownList(list, key, flags)
ObjPtr list;
int key;
long flags;
#endif
/*Does a key down in list with key and flags*/
{
ThingListPtr runner;
runner = LISTOF(list);
while (runner)
{
ObjPtr oneObject;
ObjPtr test; /*Test to see if press worked*/
oneObject = runner -> thing;
if (IsObject(oneObject))
{
ObjPtr bounds; /*The bounds of the object*/
test = KeyDownObject(oneObject, key, flags);
if (IsTrue(test))
{
return test;
}
}
else if (IsList(oneObject))
{
test = KeyDownList(oneObject, key, flags);
if (IsTrue(test))
{
return test;
}
}
runner = runner -> next;
}
return ObjFalse;
}
#ifdef PROTO
ObjPtr SortListByStringVar(ObjPtr list, NameTyp id, Bool ascending)
#else
ObjPtr SortListByStringVar(list, id, ascending)
ObjPtr list;
NameTyp id;
Bool ascending;
#endif
/*Returns a new list which is sorted by id in ascending or !ascending order.
Uses a merge sort, always a favorite of mine. Currently it's not stable,
but that could be fixed by changing how firstHalf and secondHalf are
calculated.*/
{
ObjPtr retVal;
if (((LPtr) list) -> list == ((LPtr) list) -> lastNode)
{
/*0 or 1 elements, already sorted*/
retVal = NewList();
if (LISTOF(list))
{
PrefixList(retVal, LISTOF(list) -> thing);
}
}
else
{
ObjPtr firstHalf, secondHalf;
ThingListPtr runner, firstRunner, secondRunner;
ObjPtr var;
char *test1, *test2;
int comparison;
/*Make first and second halves*/
firstHalf = NewList();
secondHalf = NewList();
runner = LISTOF(list);
while (runner)
{
PostfixList(firstHalf, runner -> thing);
runner = runner -> next;
if (runner)
{
PostfixList(secondHalf, runner -> thing);
runner = runner -> next;
}
}
/*Sort them*/
firstHalf = SortListByStringVar(firstHalf, id, ascending);
secondHalf = SortListByStringVar(secondHalf, id, ascending);
/*Merge them*/
retVal = NewList();
firstRunner = LISTOF(firstHalf);
secondRunner = LISTOF(secondHalf);
/*Do the main merge*/
while(firstRunner && secondRunner)
{
var = GetVar(firstRunner -> thing, id);
if (var)
{
test1 = GetString(var);
}
else
{
test1 = "";
}
var = GetVar(secondRunner -> thing, id);
if (var)
{
test2 = GetString(var);
}
else
{
test2 = "";
}
comparison = strcmp2(test1, test2);
if (ascending)
{
if (comparison <= 0)
{
PostfixList(retVal, firstRunner -> thing);
firstRunner = firstRunner -> next;
}
else
{
PostfixList(retVal, secondRunner -> thing);
secondRunner = secondRunner -> next;
}
}
else
{
if (comparison >= 0)
{
PostfixList(retVal, firstRunner -> thing);
firstRunner = firstRunner -> next;
}
else
{
PostfixList(retVal, secondRunner -> thing);
secondRunner = secondRunner -> next;
}
}
}
/*Take care of fiddly bits at the end*/
while(firstRunner)
{
PostfixList(retVal, firstRunner -> thing);
firstRunner = firstRunner -> next;
}
while(secondRunner)
{
PostfixList(retVal, secondRunner -> thing);
secondRunner = secondRunner -> next;
}
}
return retVal;
}
ObjPtr CleanupList(list)
ObjPtr list;
/*Method to clean up a list*/
{
EmptyList(list);
return ObjTrue;
}
void InitLists()
/*Initializes lists*/
{
listClass = NewList();
SetMethod(listClass, FINDOBJECT, FindListObject);
SetMethod(listClass, FORALLOBJECTS, ForAllListObjects);
SetMethod(listClass, MARK, MarkList);
SetMethod(listClass, PRESS, PressList);
SetMethod(listClass, TURNDIAL, TurnDialList);
SetMethod(listClass, CLEANUP, CleanupList);
AddToReferenceList(listClass);
}
void KillLists()
/*Destroys the lists*/
{
DeleteThing(listClass);
}